/*
    Project:        Home Power Control
    File:           HPCThreadedSensor.cpp
    Author:         christian@karunamusic.at
    Date:           11.2014
    Description:    Baseclass for all sensors with a measure-loop in a thread measuring at a given intervall.
 */

#include <iostream>
#include <time.h>
#include "globals.h"
#include "HPCThreadedSensor.h"

using namespace std;

pthread_mutex_t HPCThreadedSensor::m_Lock = PTHREAD_MUTEX_INITIALIZER;

HPCThreadedSensor::HPCThreadedSensor( unsigned long id, unsigned int pin, unsigned int interval )
    : HPCSensor( id, pin ), m_Run(false), m_Time(interval)
{
    PROFILE_THIS;

    m_Run = true;
    m_thrd = new boost::thread(boost::bind(&HPCThreadedSensor::mThread, this));
    if ( !m_thrd )
    {
        THROW( "could not start thread!" );
    }
}

HPCThreadedSensor::~HPCThreadedSensor()
{
    PROFILE_THIS;

    m_Run = false;
    // wait for thread to end
    m_thrd->join();
    delete m_thrd;
}

int HPCThreadedSensor::isAlarm()
{
    return m_Value.isAlarm();
}

void HPCThreadedSensor::mThread()
{
    PROFILE_THIS;

    clock_t start = clock();
    clock_t duration = 0;
    int a;
    bool av;

    while ( m_Run )
    {
        bool chg = hasChanged();
        if ( m_FireAlways || chg )
        {
            pthread_mutex_lock(&m_Lock);
            m_OnChange( this, m_Value );
            pthread_mutex_unlock(&m_Lock);
            m_Old = m_Value;
        }

        if ( m_Time )
        {
            duration = 0;
            start = clock();

            while ( m_Run && (unsigned int)duration < m_Time )
            {
                if ( m_Run && (a = isAlarm()) )
                {
                    av = (a > 0);
                    if ( !av )
                    {
                        a *= -1;
                    }
                    pthread_mutex_lock(&m_Lock);
                    m_OnAlarm( this, m_Value, av, a );
                    pthread_mutex_unlock(&m_Lock);
                }

                if ( m_Run ) Measure();
                duration = ((clock() - start) / CLOCKS_PER_SEC);
            }
            LOG( debug, "measuring paused for " << duration << " seconds" );
        }
        else
        {
            if ( (a = isAlarm()) )
            {
                av = (a > 0);
                if ( !av )
                {
                    a *= -1;
                }
                pthread_mutex_lock(&m_Lock);
                m_OnAlarm( this, m_Value, av, a );
                pthread_mutex_unlock(&m_Lock);
            }

            Measure();
        }
    }
}
